home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / clients / oclock / clock.c next >
Encoding:
C/C++ Source or Header  |  1994-08-12  |  16.3 KB  |  584 lines

  1. /*
  2.  * $XConsortium: Clock.c,v 1.24 91/05/22 17:20:31 converse Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  */
  23.  
  24. /*
  25.  * Clock.c
  26.  *
  27.  * a NeWS clone clock
  28.  */
  29.  
  30. #ifdef MSDOS
  31. #include "X11/IntrinsP.h"      /* QDK 05/19/1994 11:49am. */
  32. #else
  33. #include "X11/IntrinsicP.h"
  34. #endif
  35. #include <X11/StringDefs.h>
  36. #include <X11/Xmu/Converters.h>
  37. #include "ClockP.h"
  38. #include <X11/Xos.h>
  39. #include <stdio.h>
  40. #include <math.h>
  41. #include <X11/extensions/shape.h>
  42.  
  43. #ifdef X_NOT_STDC_ENV
  44. extern struct tm *localtime();
  45. #endif
  46.  
  47. #define offset(field) XtOffsetOf(ClockRec, clock.field)
  48. #define goffset(field) XtOffsetOf(WidgetRec, core.field)
  49.  
  50. static XtResource resources[] = {
  51.     {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
  52.         goffset(width), XtRImmediate, (XtPointer) 120},
  53.     {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
  54.     goffset(height), XtRImmediate, (XtPointer) 120},
  55.     {XtNminute, XtCForeground, XtRPixel, sizeof (Pixel),
  56.     offset(minute), XtRString, XtDefaultForeground},
  57.     {XtNhour, XtCForeground, XtRPixel, sizeof (Pixel),
  58.     offset(hour), XtRString, XtDefaultForeground},
  59.     {XtNjewel, XtCForeground, XtRPixel, sizeof (Pixel),
  60.     offset(jewel), XtRString, XtDefaultForeground},
  61.     {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
  62.         offset (backing_store), XtRString, "default"},
  63.     {XtNborderSize, XtCBorderSize, XtRFloat, sizeof (float),
  64.     offset (border_size), XtRString, "0.1"},
  65.     {XtNjewelSize, XtCBorderSize, XtRFloat, sizeof (float),
  66.     offset (jewel_size), XtRString, "0.075"},
  67.     {XtNshapeWindow, XtCShapeWindow, XtRBoolean, sizeof (Boolean),
  68.     offset (shape_window), XtRImmediate, (XtPointer) True},
  69.     {XtNtransparent, XtCTransparent, XtRBoolean, sizeof (Boolean),
  70.     offset (transparent), XtRImmediate, (XtPointer) False},
  71. };
  72.  
  73. #undef offset
  74. #undef goffset
  75.  
  76. static void     new_time();
  77.  
  78. static void Initialize(), Realize(), Destroy(), Redisplay(), Resize();
  79.  
  80. # define BORDER_SIZE(w)    ((w)->clock.border_size)
  81. # define WINDOW_WIDTH(w)    (2.0 - BORDER_SIZE(w)*2)
  82. # define WINDOW_HEIGHT(w)   (2.0 - BORDER_SIZE(w)*2)
  83. # define MINUTE_WIDTH(w)    (0.05)
  84. # define HOUR_WIDTH(w)        (0.05)
  85. # define JEWEL_SIZE(w)        ((w)->clock.jewel_size)
  86. # define MINUTE_LENGTH(w)   (JEWEL_Y(w) - JEWEL_SIZE(w) / 2.0)
  87. # define HOUR_LENGTH(w)        (MINUTE_LENGTH(w) * 0.6)
  88. # define JEWEL_X(w)        (0.0)
  89. # define JEWEL_Y(w)        (1.0 - (BORDER_SIZE(w) + JEWEL_SIZE(w)))
  90.  
  91. static void ClassInitialize();
  92.  
  93. ClockClassRec clockClassRec = {
  94.     { /* core fields */
  95.     /* superclass        */    &widgetClassRec,
  96.     /* class_name        */    "Clock",
  97.     /* size            */    sizeof(ClockRec),
  98.     /* class_initialize        */    ClassInitialize,
  99.     /* class_part_initialize    */    NULL,
  100.     /* class_inited        */    FALSE,
  101.     /* initialize        */    Initialize,
  102.     /* initialize_hook        */    NULL,
  103.     /* realize            */    Realize,
  104.     /* actions            */    NULL,
  105.     /* num_actions        */    0,
  106.     /* resources        */    resources,
  107.     /* num_resources        */    XtNumber(resources),
  108.     /* xrm_class        */    NULLQUARK,
  109.     /* compress_motion        */    TRUE,
  110.     /* compress_exposure    */    TRUE,
  111.     /* compress_enterleave    */    TRUE,
  112.     /* visible_interest        */    FALSE,
  113.     /* destroy            */    Destroy,
  114.     /* resize            */    Resize,
  115.     /* expose            */    Redisplay,
  116.     /* set_values        */    NULL,
  117.     /* set_values_hook        */    NULL,
  118.     /* set_values_almost    */    NULL,
  119.     /* get_values_hook        */    NULL,
  120.     /* accept_focus        */    NULL,
  121.     /* version            */    XtVersion,
  122.     /* callback_private        */    NULL,
  123.     /* tm_table            */    NULL,
  124.     /* query_geometry        */    XtInheritQueryGeometry,
  125.     }
  126. };
  127.  
  128. static void ClassInitialize()
  129. {
  130.     XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
  131.             NULL, 0 );
  132. }
  133.  
  134. WidgetClass clockWidgetClass = (WidgetClass) &clockClassRec;
  135.  
  136. /* ARGSUSED */
  137. static void Initialize (greq, gnew)
  138.     Widget greq, gnew;
  139. {
  140.     ClockWidget w = (ClockWidget)gnew;
  141.     XtGCMask    valuemask;
  142.     XGCValues    myXGCV;
  143.     int shape_event_base, shape_error_base;
  144.  
  145.     valuemask = GCForeground;
  146.  
  147.     if (w->clock.transparent)
  148.     {
  149.     ;
  150.     }
  151.     else
  152.     {
  153.         myXGCV.foreground = w->clock.minute;
  154.         w->clock.minuteGC = XtGetGC(gnew, valuemask, &myXGCV);
  155.  
  156.         myXGCV.foreground = w->clock.hour;
  157.         w->clock.hourGC = XtGetGC(gnew, valuemask, &myXGCV);
  158.  
  159.         myXGCV.foreground = w->clock.jewel;
  160.         w->clock.jewelGC = XtGetGC(gnew, valuemask, &myXGCV);
  161.     
  162.         myXGCV.foreground = w->core.background_pixel;
  163.         w->clock.eraseGC = XtGetGC(gnew, valuemask, &myXGCV);
  164.     }
  165.  
  166.     /* wait for Realize to add the timeout */
  167.     w->clock.interval_id = 0;
  168.  
  169.     if (w->clock.shape_window && !XShapeQueryExtension (XtDisplay (w), 
  170.                             &shape_event_base, 
  171.                             &shape_error_base))
  172.     w->clock.shape_window = False;
  173.     w->clock.shape_mask = 0;
  174.     w->clock.shapeGC = 0;
  175.     w->clock.shape_width = 0;
  176.     w->clock.shape_height = 0;
  177.     w->clock.polys_valid = 0;
  178. }
  179.  
  180. static void Resize (w)
  181.     ClockWidget    w;
  182. {
  183.     XGCValues    xgcv;
  184.     Widget    parent;
  185.     XWindowChanges    xwc;
  186.     int        face_width, face_height;
  187.     int        x, y;
  188.     Pixmap    shape_mask;
  189.  
  190.     if (!XtIsRealized((Widget) w))
  191.     return;
  192.  
  193.     /*
  194.      * compute desired border size
  195.      */
  196.  
  197.     SetTransform (&w->clock.maskt,
  198.           0, w->core.width,
  199.           w->core.height, 0,
  200.           -1.0, 1.0,
  201.            -1.0, 1.0);
  202.  
  203.     face_width = abs (Xwidth (BORDER_SIZE(w), BORDER_SIZE(w), &w->clock.maskt));
  204.     face_height = abs (Xheight (BORDER_SIZE(w), BORDER_SIZE(w), &w->clock.maskt));
  205.  
  206.     /*
  207.      *  shape the windows and borders
  208.      */
  209.  
  210.     if (w->clock.shape_window) {
  211.  
  212.     SetTransform (&w->clock.t,
  213.             face_width, w->core.width - face_width,
  214.             w->core.height - face_height, face_height,
  215.             -WINDOW_WIDTH(w)/2, WINDOW_WIDTH(w)/2,
  216.             -WINDOW_HEIGHT(w)/2, WINDOW_HEIGHT(w)/2);
  217.     
  218.     /*
  219.      * allocate a pixmap to draw shapes in
  220.      */
  221.  
  222.     if (w->clock.shape_mask &&
  223.         (w->clock.shape_width != w->core.width ||
  224.          w->clock.shape_height != w->core.height))
  225.     {
  226.         XFreePixmap (XtDisplay (w), w->clock.shape_mask);
  227.         w->clock.shape_mask = None;
  228.     }
  229.     
  230.     if (!w->clock.shape_mask)
  231.     {
  232.         w->clock.shape_mask = XCreatePixmap (XtDisplay (w), XtWindow (w),
  233.                     w->core.width, w->core.height, 1);
  234.     }
  235.     shape_mask = w->clock.shape_mask;
  236.         if (!w->clock.shapeGC)
  237.             w->clock.shapeGC = XCreateGC (XtDisplay (w), shape_mask, 0, &xgcv);
  238.  
  239.     /* erase the pixmap */
  240.         XSetForeground (XtDisplay (w), w->clock.shapeGC, 0);
  241.         XFillRectangle (XtDisplay (w), shape_mask, w->clock.shapeGC,
  242.             0, 0, w->core.width, w->core.height);
  243.         XSetForeground (XtDisplay (w), w->clock.shapeGC, 1);
  244.  
  245.     /*
  246.      * draw the bounding shape.  Doing this first
  247.      * eliminates extra exposure events.
  248.      */
  249.  
  250.     if (w->clock.border_size > 0.0 || !w->clock.transparent)
  251.     {
  252.         TFillArc (XtDisplay (w), shape_mask,
  253.                 w->clock.shapeGC, &w->clock.maskt,
  254.                 -1.0, -1.0,
  255.                 2.0, 2.0,
  256.                 0, 360 * 64);
  257.     }
  258.  
  259.     if (w->clock.transparent)
  260.     {
  261.         if (w->clock.border_size > 0.0)
  262.         {
  263.             XSetForeground (XtDisplay (w), w->clock.shapeGC, 0);
  264.             TFillArc (XtDisplay (w), shape_mask,
  265.                     w->clock.shapeGC, &w->clock.t,
  266.                     -WINDOW_WIDTH(w)/2, -WINDOW_HEIGHT(w)/2,
  267.                     WINDOW_WIDTH(w), WINDOW_HEIGHT(w),
  268.                     0, 360 * 64);
  269.             XSetForeground (XtDisplay (w), w->clock.shapeGC, 1);
  270.         }
  271.         paint_jewel (w, shape_mask, w->clock.shapeGC);
  272.         paint_hands (w, shape_mask, w->clock.shapeGC, w->clock.shapeGC);
  273.     }
  274.     /*
  275.      * Find the highest enclosing widget and shape it
  276.      */
  277.  
  278.     x = 0;
  279.     y = 0;
  280.     for (parent = (Widget) w; XtParent (parent); parent = XtParent (parent)) {
  281.         x = x + parent->core.x + parent->core.border_width;
  282.         y = y + parent->core.y + parent->core.border_width;
  283.     }
  284.  
  285.     XShapeCombineMask (XtDisplay (parent), XtWindow (parent), ShapeBounding,
  286.                 x, y, shape_mask, ShapeSet);
  287.  
  288.     /* erase the pixmap */
  289.         XSetForeground (XtDisplay (w), w->clock.shapeGC, 0);
  290.         XFillRectangle (XtDisplay (w), shape_mask, w->clock.shapeGC,
  291.             0, 0, w->core.width, w->core.height);
  292.         XSetForeground (XtDisplay (w), w->clock.shapeGC, 1);
  293.  
  294.     /*
  295.      * draw the clip shape
  296.      */
  297.  
  298.     if (w->clock.transparent)
  299.     {
  300.         paint_jewel (w, shape_mask, w->clock.shapeGC);
  301.         paint_hands (w, shape_mask, w->clock.shapeGC, w->clock.shapeGC);
  302.     }
  303.     else
  304.     {
  305.         TFillArc (XtDisplay (w), shape_mask,
  306.                 w->clock.shapeGC, &w->clock.t,
  307.                 -WINDOW_WIDTH(w)/2, -WINDOW_HEIGHT(w)/2,
  308.                 WINDOW_WIDTH(w), WINDOW_HEIGHT(w),
  309.                 0, 360 * 64);
  310.     }
  311.  
  312.     XShapeCombineMask (XtDisplay (w), XtWindow (w), ShapeClip, 
  313.             0, 0, shape_mask, ShapeSet);
  314.  
  315.     } else
  316.     {
  317.         /*
  318.           * reconfigure the widget to split the availible
  319.           * space between the window and the border
  320.           */
  321.  
  322.          if (face_width > face_height)
  323.         xwc.border_width = face_height;
  324.         else
  325.         xwc.border_width = face_width;
  326.         xwc.width = w->core.width - xwc.border_width * 2;
  327.         xwc.height = w->core.height - xwc.border_width * 2;
  328.         XConfigureWindow (XtDisplay (w), XtWindow (w),
  329.                 CWWidth|CWHeight|CWBorderWidth,
  330.                 &xwc);
  331.     
  332.         SetTransform (&w->clock.t,
  333.         0, xwc.width,
  334.         xwc.height, 0,
  335.         -WINDOW_WIDTH(w)/2, WINDOW_WIDTH(w)/2,
  336.         -WINDOW_HEIGHT(w)/2, WINDOW_HEIGHT(w)/2);
  337.     }
  338. }
  339.  
  340. static void Realize (gw, valueMask, attrs)
  341.      Widget gw;
  342.      XtValueMask *valueMask;
  343.      XSetWindowAttributes *attrs;
  344. {
  345.      ClockWidget    w = (ClockWidget)gw;
  346.  
  347.     if (w->clock.backing_store != Always + WhenMapped + NotUseful) {
  348.          attrs->backing_store = w->clock.backing_store;
  349.     *valueMask |= CWBackingStore;
  350.     }
  351.     if (w->clock.transparent)
  352.     {
  353.     attrs->background_pixel = w->clock.minute;
  354.     *valueMask |= CWBackPixel;
  355.     *valueMask &= ~CWBackPixmap;
  356.     }
  357.     XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
  358.              *valueMask, attrs );
  359.     if (!w->clock.transparent)
  360.     Resize (w);
  361.     new_time ((XtPointer) gw, 0);
  362. }
  363.  
  364. static void Destroy (gw)
  365.      Widget gw;
  366. {
  367.      ClockWidget w = (ClockWidget)gw;
  368.      if (w->clock.interval_id) XtRemoveTimeOut (w->clock.interval_id);
  369.      if (! w->clock.transparent) {
  370.      XtReleaseGC(gw, w->clock.minuteGC);
  371.      XtReleaseGC(gw, w->clock.hourGC);
  372.      XtReleaseGC(gw, w->clock.jewelGC);
  373.      XtReleaseGC(gw, w->clock.eraseGC);
  374.      }
  375.      if (w->clock.shapeGC)
  376.     XFreeGC(XtDisplay(gw), w->clock.shapeGC);
  377.     if (w->clock.shape_mask)
  378.     XFreePixmap (XtDisplay (w), w->clock.shape_mask);
  379. }
  380.  
  381. /* ARGSUSED */
  382. static void Redisplay(gw, event, region)
  383.      Widget gw;
  384.      XEvent *event;
  385.      Region region;
  386. {
  387.     ClockWidget    w;
  388.  
  389.     w = (ClockWidget) gw;
  390.     if (!w->clock.transparent)
  391.     {
  392.         paint_jewel (w, XtWindow (w), w->clock.jewelGC);
  393.         paint_hands (w, XtWindow (w), w->clock.minuteGC, w->clock.hourGC);
  394.     }
  395. }
  396.  
  397. /*
  398.  * routines to draw the hands and jewel
  399.  */
  400.  
  401. #ifndef PI    /* may be found in <math.h> */
  402. # define PI (3.14159265358979323846)
  403. #endif
  404.  
  405. /*
  406.  * converts a number from 0..1 representing a clockwise radial distance
  407.  * from the 12 oclock position to a radian measure of the counter-clockwise
  408.  * distance from the 3 oclock position
  409.  */
  410.  
  411. static double
  412. clock_to_angle (clock)
  413. double    clock;
  414. {
  415.     if (clock >= .75)
  416.         clock -= 1.0;
  417.     return -2.0 * PI * clock + PI / 2.0;
  418. }
  419.  
  420. /* ARGSUSED */
  421. static void new_time (client_data, id)
  422.      XtPointer client_data;
  423.      XtIntervalId *id;        /* unused */
  424. {
  425.         ClockWidget    w = (ClockWidget)client_data;
  426.     long        now;
  427.     struct tm    *tm;
  428.     
  429.     if (!w->clock.transparent)
  430.     if (w->clock.polys_valid) {
  431.         paint_hands (w, XtWindow (w), w->clock.eraseGC, w->clock.eraseGC);
  432.         check_jewel (w, XtWindow (w), w->clock.jewelGC);
  433.     }
  434.     (void) time (&now);
  435.     tm = localtime (&now);
  436.     if (tm->tm_hour >= 12)
  437.         tm->tm_hour -= 12;
  438.     w->clock.hour_angle = clock_to_angle ((((double) tm->tm_hour) +
  439.                 ((double) tm->tm_min) / 60.0) / 12.0);
  440.     w->clock.minute_angle =
  441.         clock_to_angle (((double) tm->tm_min) / 60.0);
  442.     /*
  443.      * add the timeout before painting the hands, that may
  444.      * take a while and we'd like the clock to keep up
  445.      * with time changes.
  446.      */
  447.     w->clock.interval_id = 
  448.         XtAppAddTimeOut (XtWidgetToApplicationContext((Widget) w),
  449.                  (60 - tm->tm_sec) * 1000, new_time, client_data);
  450.     compute_hands (w);
  451.     if (w->clock.transparent)
  452.         Resize (w);
  453.     else
  454.         paint_hands (w, XtWindow (w), w->clock.minuteGC, w->clock.hourGC);
  455. } /* new_time */
  456.  
  457. paint_jewel (w, d, gc)
  458. ClockWidget w;
  459. Drawable    d;
  460. GC        gc;
  461. {
  462.     if (JEWEL_SIZE(w) > 0.0)
  463.     {
  464.     TFillArc (XtDisplay (w), d, gc, &w->clock.t,
  465.             JEWEL_X(w) - JEWEL_SIZE(w) / 2.0,
  466.              JEWEL_Y(w) - JEWEL_SIZE(w) / 2.0,
  467.              JEWEL_SIZE(w), JEWEL_SIZE(w), 0, 360 * 64);
  468.     }
  469. }
  470.  
  471. #define sqr(x)    ((x)*(x))
  472.  
  473. /*
  474.  * check to see if the polygon intersects the circular jewel
  475.  */
  476.  
  477. check_jewel_poly (w, poly)
  478. ClockWidget    w;
  479. TPoint        poly[POLY_SIZE];
  480. {
  481.     double    a2, b2, c2, d2;
  482.     double    x, y, size;
  483.     int    i;
  484.  
  485.     if (JEWEL_SIZE(w) > 0.0)
  486.     {
  487.     x = JEWEL_X(w);
  488.     y = JEWEL_Y(w);
  489.     size = JEWEL_SIZE(w);
  490.     /*
  491.      * check each side of the polygon to see if the
  492.      * distance from the line to the center of the
  493.      * circular jewel is less than the radius.
  494.      */
  495.     for (i = 0; i < POLY_SIZE-1; i++) {
  496.         a2 = sqr (poly[i].x - x) + sqr (poly[i].y - y);
  497.         b2 = sqr (poly[i+1].x - x) + sqr (poly[i+1].y - y);
  498.         c2 = sqr (poly[i].x - poly[i+1].x) + sqr (poly[i].y - poly[i+1].y);
  499.         d2 = a2 + b2 - c2;
  500.         if (d2 <= sqr (size) &&
  501.             a2 <= 2 * c2 && b2 <= 2 * c2 ||
  502.              a2 <= sqr (size) ||
  503.             b2 <= sqr (size))
  504.             return 1;
  505.     }
  506.     }
  507.     return 0;
  508. }
  509.  
  510. check_jewel (w, d, gc)
  511. ClockWidget    w;
  512. Drawable    d;
  513. GC        gc;
  514. {
  515.     if (!w->clock.polys_valid || JEWEL_SIZE(w) <= 0.0)
  516.         return;
  517.     if ((MINUTE_LENGTH(w) >= (JEWEL_Y(w) - JEWEL_SIZE(w)/2.0) &&
  518.          check_jewel_poly (w, w->clock.minute_poly)) ||
  519.         (HOUR_LENGTH(w) >= (JEWEL_Y(w) - JEWEL_SIZE(w)/2.0) &&
  520.          check_jewel_poly (w, w->clock.minute_poly)))
  521.     {
  522.         paint_jewel (w, d, gc);
  523.     }
  524. }
  525.  
  526. /*
  527.  * A hand is a rectangle with a triangular cap at the far end.
  528.  * This is represented with a five sided polygon.
  529.  */
  530.  
  531. compute_hand (w, a, l, width, poly)
  532. ClockWidget    w;
  533. double        a, l, width;
  534. TPoint        poly[POLY_SIZE];
  535. {
  536.     double    c, s;
  537.  
  538.     c = cos(a);
  539.     s = sin(a);
  540.     poly[0].x = c * l;    
  541.     poly[0].y = s * l;
  542.     poly[1].x = (l - width) * c - s * width;
  543.     poly[1].y = (l - width) * s + c * width;
  544.     poly[2].x = (-width) * c - s * width;
  545.     poly[2].y = (-width) * s + c * width;
  546.     poly[3].x = (-width) * c + s * width;
  547.     poly[3].y = (-width) * s - c * width;
  548.     poly[4].x = (l - width) * c + s * width;
  549.     poly[4].y = (l - width) * s - c * width;
  550.     poly[5].x = poly[0].x;
  551.     poly[5].y = poly[0].y;
  552. }
  553.  
  554. compute_hands (w)
  555. ClockWidget    w;
  556. {
  557.     compute_hand (w, w->clock.minute_angle,
  558.         MINUTE_LENGTH(w), MINUTE_WIDTH(w), w->clock.minute_poly);
  559.     compute_hand (w, w->clock.hour_angle,
  560.         HOUR_LENGTH(w), HOUR_WIDTH(w), w->clock.hour_poly);
  561.     w->clock.polys_valid = 1;
  562. }
  563.  
  564. paint_hand (w, d, gc, poly)
  565. ClockWidget    w;
  566. Drawable    d;
  567. GC        gc;
  568. TPoint        poly[POLY_SIZE];
  569. {
  570.     TFillPolygon (XtDisplay (w), d, gc, &w->clock.t, poly, POLY_SIZE,
  571.             Convex, CoordModeOrigin);
  572. }
  573.  
  574. paint_hands (w, d, minute_gc, hour_gc)
  575. ClockWidget    w;
  576. Drawable    d;
  577. GC        minute_gc, hour_gc;
  578. {
  579.     if (w->clock.polys_valid) {
  580.     paint_hand (w, d, hour_gc, w->clock.hour_poly);
  581.     paint_hand (w, d, minute_gc, w->clock.minute_poly);
  582.     }
  583. }
  584.